﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;

namespace Cofe.Core.Security
{
    [Export(typeof(ICofeService))]
    [ServicePriority(ServicePriorityAttribute.DefaultPriority_COFE)]
    public class UserManager : UserManagerBase, ISaveSettings
    {
        public UserManager()
            : base(new GenericPrincipalPolicy(new string[] { }))
        {

        }

        public Task SaveAsync(Session.ICofeSettings settings)
        {
            return Task.Run(() =>
                {
                    if (CofeServices.UserManager == this)
                    {
                        settings.UserPermissions = new Session.UserPolicyList(this.GetPrincipalPolicies());
                    }
                });
        }

        public Task RestoreAsync(Session.ICofeSettings settings)
        {
            return Task.Run(() =>
            {
                if (CofeServices.UserManager == this)
                {
                    _policies = new List<IPrincipalPolicy>(settings.UserPermissions.ToArray());
                }
            });
        }
    }

    public abstract class UserManagerBase : IUserManager
    {
        #region Constructor

        public UserManagerBase(params IPrincipalPolicy[] policies)
        {
            if (policies == null || policies.Length == 0)
                throw new ArgumentException("No policy defined.");
            _policies = new List<IPrincipalPolicy>(policies);
        }

        #endregion

        #region Methods

        public IEnumerable<IPrincipalPolicy> GetPrincipalPolicies()
        {
            return new List<IPrincipalPolicy>(_policies);
        }

        protected IPrincipal createPrincipal(IPrincipalPolicy[] policies, IIdentity identity, bool isServiceIdentity)
        {
            return new CofePrincipal(policies, identity, identity is ServiceIdentity);
        }

        public virtual IPrincipal GetPrincipal(IIdentity identity = null)
        {
            if (identity == null)
                return createPrincipal(_policies.ToArray(), null, false);

            return createPrincipal(_policies.ToArray(), identity, identity is ServiceIdentity);
        }

        public void AddPrincipalPolicy(IPrincipalPolicy policy)
        {
            _policies.Add(policy);
        }

        public void RemovePrincipalPolicy(Func<IPrincipalPolicy, bool> filter)
        {
            foreach (var p in _policies.ToArray())
                if (filter(p))
                    _policies.Remove(p);
        }

        #endregion

        #region Data

        protected List<IPrincipalPolicy> _policies = new List<IPrincipalPolicy>();

        #endregion

        #region Public Properties

        #endregion


    }
}
